package com.msk.third.service;

import com.alibaba.fastjson2.JSON;
import com.aliyuncs.DefaultAcsClient;
import com.aliyuncs.auth.sts.AssumeRoleRequest;
import com.aliyuncs.auth.sts.AssumeRoleResponse;
import com.aliyuncs.exceptions.ClientException;
import com.aliyuncs.profile.DefaultProfile;
import com.aliyuncs.profile.IClientProfile;
import com.msk.common.core.redis.RedisCache;
import com.msk.third.config.AliOssConfig;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;

import static com.msk.common.constant.CacheConstants.MP_OSS_TOKEN_KEY;

/**
 * @BelongsProject: msk
 * @BelongsPackage: com.msk.common.third.aliyun.service
 * @Author: dz
 * @CreateTime: 2022-06-27  11:42
 * @Description: 小程序获取oss token信息
 * @Version: 1.0
 */
@Service
public class OssStsTokenMpService {

    private static Logger logger = LoggerFactory.getLogger(OssStsTokenMpService.class);

    private final long EXPIRE_TIME = 43200L;

    @Autowired
    private RedisCache redisService;

    @Autowired
    private AliOssConfig aliOssConfig;

    /**
     * 获取token信息
     * @param type
     * @return
     */
    public Map<String,Object> getTokenInfo(String type){

        if (redisService.keyIsExists(MP_OSS_TOKEN_KEY)) {
            return redisService.getCacheObject(MP_OSS_TOKEN_KEY);
        }

        Map<String,Object> resultMap = new HashMap(4);

        // STS接入地址，例如sts.cn-hangzhou.aliyuncs.com。
        String endpoint = aliOssConfig.getStsEndPoint();
        // 填写步骤1生成的访问密钥AccessKey ID和AccessKey Secret。
        String AccessKeyId = aliOssConfig.getAccessKeyId();
        String accessKeySecret = aliOssConfig.getAccessKeySecret();
        // 填写步骤3获取的角色ARN。
        String roleArn = aliOssConfig.getRoleArn();
        // 自定义角色会话名称，用来区分不同的令牌，例如可填写为SessionTest。
        String roleSessionName = type;
        // 以下Policy用于限制仅允许使用临时访问凭证向目标存储空间examplebucket上传文件。
        // 临时访问凭证最后获得的权限是步骤4设置的角色权限和该Policy设置权限的交集，即仅允许将文件上传至目标存储空间examplebucket下的exampledir目录。
        String policy = "{\"Version\":\"1\",\"Statement\":[{\"Effect\":\"Allow\",\"Action\":\"oss:PutObject\",\"Resource\":[\"acs:oss:*:*:dayuzhongxue-user/image\",\"acs:oss:*:*:dayuzhongxue-user/video\"]}]}";
        try {
            // regionId表示RAM的地域ID。以华东1（杭州）地域为例，regionID填写为cn-hangzhou。也可以保留默认值，默认值为空字符串（""）。
            String regionId = "cn-beijing";
            // 添加endpoint。适用于Java SDK 3.12.0及以上版本。
//            DefaultProfile.addEndpoint(regionId, "Sts", endpoint);
            // 添加endpoint。适用于Java SDK 3.12.0以下版本。
            DefaultProfile.addEndpoint("",regionId, "Sts", endpoint);
            // 构造default profile。
            IClientProfile profile = DefaultProfile.getProfile(regionId, AccessKeyId, accessKeySecret);
            // 构造client。
            DefaultAcsClient client = new DefaultAcsClient(profile);
            final AssumeRoleRequest request = new AssumeRoleRequest();
            // 适用于Java SDK 3.12.0及以上版本。
//            request.setSysMethod(MethodType.POST);
            // 适用于Java SDK 3.12.0以下版本。
            //request.setMethod(MethodType.POST);
            request.setRoleArn(roleArn);
            request.setRoleSessionName(roleSessionName);
//            request.setPolicy(policy); // 如果policy为空，则用户将获得该角色下所有权限。
            // 设置临时访问凭证的有效时间为3600秒。
            request.setDurationSeconds(EXPIRE_TIME);
            final AssumeRoleResponse response = client.getAcsResponse(request);
            resultMap.put("accessKeyId",response.getCredentials().getAccessKeyId());
            resultMap.put("accessKeySecret",response.getCredentials().getAccessKeySecret());
            resultMap.put("token",response.getCredentials().getSecurityToken());
            resultMap.put("expiration",response.getCredentials().getExpiration());
            logger.info("tokenInfo:{}", JSON.toJSONString(resultMap));
            redisService.setCacheObject(MP_OSS_TOKEN_KEY, resultMap,36000, TimeUnit.SECONDS);
        } catch (ClientException e) {
            resultMap.clear();
            logger.error("获取oss token异常 Error code:{},Error message:{},RequestId:{}",e.getErrCode(),e.getErrMsg(),e.getRequestId());
        }
        return resultMap;
    }

}
